<template>
	<view class="prize-wheel" ref="prizewheel" :style="{'width':wheelWidth+'rpx','height':wheelHeight+'rpx'}">

		<canvas canvas-id="prizeWheel" id="prizeWheel" class="prize-wheel-canvas"></canvas>
		<view class="prize-wheel-img-wrapper" v-if="prizeWheelImg" @transitionend="transitionend"
			:class="{ 'rotaing': isRotating }"
			:style="{ 'transform': `rotate(${currentRotationAngle}deg)`,'transition-duration':`${rotateDuration}s` }">
			<image :src="prizeWheelImg" mode="" class="prize-wheel-img"></image>
		</view>

		<view class="pointer-img-wrapper" @click="clickStart">
			<image
				:src="pointerImg?pointerImg:'https://mp-a6359cef-e1f5-4478-96f8-00fab19c712c.cdn.bspapp.com/cloudstorage/72e75195-fc20-452d-80d3-ebe1dc35d966.png'"
				class="pointer-img" />
		</view>

	</view>
</template>



<script lang="ts" setup>
	import {
		onMounted,
		ref,
		toRefs,
		Ref
	} from 'vue';
	import {
		getCurrentInstance,
		defineProps,
		defineExpose,
		defineEmits
	} from 'vue';

	interface IPrizeWheelProps {
		//转盘宽度
		wheelWidth: number;
		//转盘高度
		wheelHeight: number;
		//奖品列表
		prizeList: IPrizeItem[];
		//转盘背景颜色列表
		wheelItemBgColor: IWheelItemBgColorItem[];
		//图片参数
		prizeImgConfig ? : IPrizeImgConfig;
		//文字参数
		prizeNameConfig ? : IPrizeNameConfig;
		//旋转时长
		rotateDuration ? : number;
		//旋转圈数
		rotateCount ? : number;
		//指针图片
		pointerImg ? : string;
	}

	const emit = defineEmits(['clickStart'])

	const props = withDefaults(defineProps < IPrizeWheelProps > (), {
		wheelWidth: 622,
		wheelHeight: 622,
		prizeImgConfig: () => {
			return {
				offsetTop: 65,
				width: 30,
				height: 30,
			}
		},
		prizeNameConfig: () => {
			return {
				offsetTop: 50,
				fontSize: 14,
				fontFamily: ' Microsoft Yahei',
				colorList: ['#CF5300', '#ffffff'],
			}
		},
		rotateCount: 10,
		rotateDuration: 5,
	});

	console.log(props)

	const {
		prizeList,
		wheelItemBgColor,
		rotateCount
	} = toRefs(props);

	//元素在375设计稿下的实际宽度
	const width: number = props.wheelWidth / 2;
	//元素在375设计稿下的实际高度
	const height: number = props.wheelWidth / 2;
	//当前手机对于375设计稿的元素缩放比
	const scale_ratio: number = uni.getWindowInfo().screenWidth / 375;
	//每一项的角度
	const angle: number = Math.PI * 2 / prizeList.value.length;
	//是否正在旋转
	const isRotating: Ref < boolean > = ref(false);
	//当前奖盘的落点位置
	const currentIndex: Ref < number > = ref(0);
	//当前总旋转角度
	const currentRotationAngle: Ref < number > = ref(0);
	//生成的奖盘图片
	const prizeWheelImg: Ref < string > = ref('');

	onMounted(() => {

				const instance = getCurrentInstance();
				const ctx = uni.createCanvasContext("prizeWheel", instance);
				ctx.scale(scale_ratio, scale_ratio);
				drawWheel();


				async function drawWheel() {
					ctx.translate(width / 2, height / 2)
					ctx.rotate(-((Math.PI / 2) + (angle / 2)));
					ctx.translate(-width / 2, -height / 2);
					ctx.save();
					for (let i = 0; i < prizeList.value.length; i++) {
						ctx.save();
						const beginAngle = angle * i;
						const bgColor = getArrayItemByIndex(wheelItemBgColor.value, i);
						drawWheelItem(beginAngle, bgColor);
						ctx.translate(width / 2, height / 2)
						ctx.rotate((Math.PI / 2) + angle / 2 + beginAngle);
						ctx.translate(-width / 2, -height / 2);
						const localImgPath = await getImageInfo(prizeList.value[i].prizeImg);
						const textColor = getArrayItemByIndex(props.prizeNameConfig.colorList!, i);
						drawPrizeItem(prizeList.value[i].prizeName, localImgPath, textColor);
						ctx.restore();
					}
					ctx.draw(false, () => {
						uni.canvasToTempFilePath({
							canvasId: 'prizeWheel',
							success: (res) => {
								prizeWheelImg.value = res.tempFilePath;
							}
						}, instance)
					});
				}

				function drawWheelItem(beginAngle: number, bgColor: IWheelItemBgColorItem): void {
					ctx.beginPath();
					if (bgColor.gradientColor) {
						let linearGradient = ctx.createCircularGradient(width / 2, height / 2, width / 2);
						for (let key in bgColor.gradientColor) {
							linearGradient.addColorStop(key, bgColor.gradientColor[key]);
						}
						ctx.fillStyle = linearGradient;
						ctx.strokeStyle = bgColor.gradientColor[0];
					} else if (bgColor.color) {
						ctx.fillStyle = bgColor.color;
						ctx.strokeStyle = bgColor.color;
					} else {
						ctx.fillStyle = '#ffffff';
					}
					ctx.moveTo(width / 2, height / 2);
					ctx.arc(width / 2, height / 2, width / 2, beginAngle, beginAngle + angle, false);
					ctx.fill();
					ctx.stroke();
					ctx.closePath();
				}

				function drawPrizeItem(prizeName: string, prizeImg: string, textColor: string): void {
					ctx.beginPath();
					ctx.fillStyle = textColor;
					ctx.font = `${props.prizeNameConfig.fontSize}px ${props.prizeNameConfig.fontFamily}`;
					if (prizeImg) {
						ctx.drawImage(prizeImg, (width / 2 - (props.prizeImgConfig.width!/ 2)), props.prizeImgConfig
									.offsetTop, props.prizeImgConfig.width, props.prizeImgConfig.height);
							}
							ctx.setTextAlign('center'); ctx.fillText(prizeName, width / 2, props.prizeNameConfig
								.offsetTop!); ctx.fill(); ctx.closePath();
						}


						function getImageInfo(src: string): Promise < string > {
							return new Promise((resolve) => {
								uni.getImageInfo({
									src,
									success: (res) => {
										// #ifdef H5
										resolve('/cloudstorage'+res.path.split('/cloudstorage')[1])
										// #endif
										
										// #ifndef H5
										resolve(res.path)
										// #endif
									},
									fail: (err) => {
										console.log(err);
										resolve('')
									}
								})
							})
						}

					})

				function getArrayItemByIndex < T > (arr: T[], index: number): T {
					return arr[index > arr.length - 1 ? index % arr.length : index];
				}

				function start(index: number): void {
					if (isRotating.value) {
						return
					}
					const rotateIntervalItemCount: number = index >= currentIndex.value ? index - currentIndex
						.value : prizeList.value.length - currentIndex.value + index;
					currentIndex.value = index;
					currentRotationAngle.value += ((Math.PI * 2 * rotateCount.value) + (Math.PI * 2 -
						rotateIntervalItemCount *
						angle)) * 180 / Math.PI;
					isRotating.value = true;
				}

				function transitionend() {
					isRotating.value = false;
				}

				function clickStart() {
					emit('clickStart')
				}


				defineExpose({
					start,
					isRotating
				})
</script>

<style scoped lang="scss">
	@import "./style.scss";
</style>
